﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Ivory
{    
    public sealed class InputControl : GameComponent
    {
        public enum MouseKey {
            Left = 0,
            Right,
            Middle,
        }
        
        //Fields
        private MouseState LastFrameMouseState, CurrentFrameMouseState;
        private KeyboardState LastFrameKeyboardState, CurrentFrameKeyboardState;

        public Vector2 MouseVect 
        { 
            get 
            {
                if (CurrentFrameMouseState == null)
                    return new Vector2(-1, -1);
                return new Vector2(CurrentFrameMouseState.X, CurrentFrameMouseState.Y);
            }
        }
        public Point MousePoint
        { 
            get 
            {
                if (CurrentFrameMouseState == null)
                    return new Point(-1, -1);
                return new Point(CurrentFrameMouseState.X, CurrentFrameMouseState.Y); 
            } 
        }

        //Construct
        public InputControl(Game game)
            : base(game)
        {

        }

        //Methods
        public override void Update(GameTime time)
        {
            //Update Mouse states
            if (CurrentFrameMouseState != null)
                LastFrameMouseState = CurrentFrameMouseState;
            CurrentFrameMouseState = Mouse.GetState();

            //Update Keyboard states
            if (CurrentFrameKeyboardState != null)
                LastFrameKeyboardState = CurrentFrameKeyboardState;
            CurrentFrameKeyboardState = Keyboard.GetState();
        }

        public bool IsKeyDown(Keys key)
        {
            return CurrentFrameKeyboardState.IsKeyDown(key);
        }
        public bool IsNewKeyPress(Keys key)
        {
            return CurrentFrameKeyboardState.IsKeyDown(key) && LastFrameKeyboardState.IsKeyUp(key);
        }

        public Keys[] GetKeysDown()
        {
            return CurrentFrameKeyboardState.GetPressedKeys();
        }

        private bool IsClicked(MouseKey key)
        {
            switch (key)
            {
                case MouseKey.Left: return (CurrentFrameMouseState.LeftButton == ButtonState.Pressed) 
                                        && (LastFrameMouseState.LeftButton == ButtonState.Released);
                
                case MouseKey.Middle: return CurrentFrameMouseState.MiddleButton == ButtonState.Pressed
                                        && (LastFrameMouseState.MiddleButton == ButtonState.Released);
                
                case MouseKey.Right: return CurrentFrameMouseState.RightButton == ButtonState.Pressed
                                        && (LastFrameMouseState.RightButton == ButtonState.Released);
            }

            return false;
        }

        public bool IsLeftClick()
        {
            return IsClicked(MouseKey.Left);
        }
        public bool IsRightClick()
        {
            return IsClicked(MouseKey.Right);
        }
        public bool IsMiddleClick()
        {
            return IsClicked(MouseKey.Middle);
        }

        public bool IsMouseButtonDown(MouseKey key)
        {
            switch (key)
            {
                case MouseKey.Left: return CurrentFrameMouseState.LeftButton == ButtonState.Pressed;
                case MouseKey.Middle: return CurrentFrameMouseState.MiddleButton == ButtonState.Pressed;
                case MouseKey.Right: return CurrentFrameMouseState.RightButton == ButtonState.Pressed;
            }

            return false;
        }
        public bool IsRectClicked(MouseKey key, Rectangle rect)
        {
            switch (key)
            {
                case MouseKey.Left: return IsLeftClick() && rect.Contains(MousePoint);
                case MouseKey.Middle: return IsMiddleClick() && rect.Contains(MousePoint);
                case MouseKey.Right: return IsRightClick() && rect.Contains(MousePoint);
            }
            return false;
        }
    }
}
